package com.zycfc.zsf.boot.job.core;

import com.dangdang.ddframe.job.lite.api.strategy.*;
import com.dangdang.ddframe.job.reg.zookeeper.*;
import com.zycfc.zsf.boot.core.common.*;
import com.zycfc.zsf.boot.job.enums.*;
import java.util.*;
import org.slf4j.*;

public class ZsfAverageAllocationJobShardingStrategy implements JobShardingStrategy
{
    private static final Logger log;
    private final Random random;
    
    public ZsfAverageAllocationJobShardingStrategy() {
        this.random = new Random();
    }
    
    public Map<JobInstance, List<Integer>> sharding(final List<JobInstance> jobInstances, final String jobName, final int shardingTotalCount) {
        ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-start", (Object)jobName);
        Map<JobInstance, List<Integer>> result = null;
        try {
            final ZsfJobNodePath zsfJobNodePath = new ZsfJobNodePath(jobName);
            final String shardingStrategy = ((ZookeeperRegistryCenter)SpringContextHelper.getBean("zookeeperRegistryCenter", (Class)ZookeeperRegistryCenter.class)).get(zsfJobNodePath.getShardingStrategyNodePath());
            final String fixedIp = ((ZookeeperRegistryCenter)SpringContextHelper.getBean("zookeeperRegistryCenter", (Class)ZookeeperRegistryCenter.class)).get(zsfJobNodePath.getShardingFixedIpNodePath());
            if (jobInstances.isEmpty()) {
                ZsfAverageAllocationJobShardingStrategy.log.error("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-error-reason: jobInstances is null", (Object)jobName);
                return Collections.emptyMap();
            }
            if (shardingTotalCount == 1 && ShardingStrategy.RANDOM.getValue().equals(shardingStrategy)) {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-info: \u5f53\u524d\u603b\u5206\u7247\u7b49\u4e8e1\uff0c\u6267\u884c\u968f\u673a\u5206\u7247\u903b\u8f91", (Object)jobName);
                result = this.shardingRandom(jobInstances, jobName, shardingTotalCount);
            }
            else if (shardingTotalCount == 1 && ShardingStrategy.IP_HASH_MAX.getValue().equals(shardingStrategy)) {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-info: \u5f53\u524d\u603b\u5206\u7247\u7b49\u4e8e1\uff0c\u6267\u884cip hash\u5206\u7247\u903b\u8f91", (Object)jobName);
                result = this.shardingFixedInstance(jobInstances, shardingTotalCount);
            }
            else if (shardingTotalCount == 1 && ShardingStrategy.IP_FIXED.getValue().equals(shardingStrategy)) {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-info: \u5f53\u524d\u603b\u5206\u7247\u7b49\u4e8e1\uff0c\u6267\u884cip fixed\u56fa\u5b9aip\u5206\u7247\u903b\u8f91", (Object)jobName);
                result = this.shardingIpFixedInstance(jobInstances, shardingTotalCount, jobName, fixedIp);
            }
            else {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-info: \u6267\u884c\u9ed8\u8ba4\u5e73\u5747\u5206\u7247\u903b\u8f91", (Object)jobName);
                result = this.shardingAliquot(jobInstances, shardingTotalCount);
                this.addAliquant(jobInstances, shardingTotalCount, result);
            }
            if (shardingTotalCount == 1) {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-ShardingStrategy-success-{}-result-{}", (Object)jobName, (Object)this.getShardingInfo(jobInstances, result));
            }
            else {
                ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-multi-ShardingStrategy-success-{}-result-{}", (Object)jobName, (Object)this.getShardingInfo(jobInstances, result));
            }
        }
        catch (Exception e) {
            ZsfAverageAllocationJobShardingStrategy.log.error("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-error-reason:", (Object)jobName, (Object)e);
            return Collections.emptyMap();
        }
        return result;
    }
    
    private String getShardingInfo(final List<JobInstance> jobInstances, final Map<JobInstance, List<Integer>> result) {
        final StringBuilder sb = new StringBuilder();
        sb.append("jobInstances is ");
        for (final JobInstance jobInstance : jobInstances) {
            sb.append(jobInstance.getJobInstanceId()).append("|");
        }
        sb.append(", result is ");
        for (final Map.Entry entry : result.entrySet()) {
            sb.append(entry.getKey().getJobInstanceId()).append(":").append(entry.getValue().toString()).append("|");
        }
        return sb.toString();
    }
    
    private Map<JobInstance, List<Integer>> shardingFixedInstance(final List<JobInstance> shardingUnits, final int shardingTotalCount) {
        final Map<JobInstance, List<Integer>> result = new LinkedHashMap<JobInstance, List<Integer>>(shardingTotalCount, 1.0f);
        JobInstance fixJobInstance = null;
        int maxHash = 0;
        for (final JobInstance each : shardingUnits) {
            final int jobIpHash = Math.abs(each.getIp().hashCode());
            if (jobIpHash > maxHash) {
                maxHash = jobIpHash;
                fixJobInstance = each;
            }
        }
        if (fixJobInstance == null) {
            throw new IllegalArgumentException("zsfJob: \u56fa\u5b9aIP\u5206\u7247\u6267\u884c\u5f02\u5e38");
        }
        final List<Integer> shardingItems = new ArrayList<Integer>(shardingTotalCount);
        shardingItems.add(0);
        result.put(fixJobInstance, shardingItems);
        return result;
    }
    
    private Map<JobInstance, List<Integer>> shardingIpFixedInstance(final List<JobInstance> shardingUnits, final int shardingTotalCount, final String jobName, final String fixedIp) {
        Map<JobInstance, List<Integer>> result = new LinkedHashMap<JobInstance, List<Integer>>(shardingTotalCount, 1.0f);
        JobInstance fixJobInstance = null;
        for (final JobInstance each : shardingUnits) {
            final String jobIp = each.getIp();
            if (jobIp.equals(fixedIp)) {
                fixJobInstance = each;
                break;
            }
        }
        if (fixJobInstance == null) {
            ZsfAverageAllocationJobShardingStrategy.log.warn("elasticJob-{}-jobStep-sharding-isLeader-ShardingStrategy-info-fixedIp\u672a\u627e\u5230\u5bf9\u5e94\u7684IP\uff0c\u6267\u884c\u9ed8\u8ba4\u5e73\u5747\u5206\u7247\u903b\u8f91", (Object)jobName);
            result = this.shardingAliquot(shardingUnits, shardingTotalCount);
            this.addAliquant(shardingUnits, shardingTotalCount, result);
            return result;
        }
        final List<Integer> shardingItems = new ArrayList<Integer>(shardingTotalCount);
        shardingItems.add(0);
        result.put(fixJobInstance, shardingItems);
        return result;
    }
    
    private Map<JobInstance, List<Integer>> shardingRandom(final List<JobInstance> jobInstances, final String jobName, final int shardingTotalCount) {
        final Map<JobInstance, List<Integer>> result = new LinkedHashMap<JobInstance, List<Integer>>(shardingTotalCount, 1.0f);
        final int randomInt = this.random.nextInt(jobInstances.size());
        final JobInstance jobInstance = jobInstances.get(randomInt);
        final List<Integer> shardingItems = new ArrayList<Integer>(shardingTotalCount);
        shardingItems.add(0);
        result.put(jobInstance, shardingItems);
        return result;
    }
    
    private Map<JobInstance, List<Integer>> shardingAliquot(final List<JobInstance> shardingUnits, final int shardingTotalCount) {
        final Map<JobInstance, List<Integer>> result = new LinkedHashMap<JobInstance, List<Integer>>(shardingTotalCount, 1.0f);
        final int itemCountPerSharding = shardingTotalCount / shardingUnits.size();
        int count = 0;
        for (final JobInstance each : shardingUnits) {
            final List<Integer> shardingItems = new ArrayList<Integer>(itemCountPerSharding + 1);
            for (int i = count * itemCountPerSharding; i < (count + 1) * itemCountPerSharding; ++i) {
                shardingItems.add(i);
            }
            result.put(each, shardingItems);
            ++count;
        }
        return result;
    }
    
    private void addAliquant(final List<JobInstance> shardingUnits, final int shardingTotalCount, final Map<JobInstance, List<Integer>> shardingResults) {
        final int aliquant = shardingTotalCount % shardingUnits.size();
        int count = 0;
        for (final Map.Entry<JobInstance, List<Integer>> entry : shardingResults.entrySet()) {
            if (count < aliquant) {
                entry.getValue().add(shardingTotalCount / shardingUnits.size() * shardingUnits.size() + count);
            }
            ++count;
        }
    }
    
    static {
        log = LoggerFactory.getLogger((Class)ZsfAverageAllocationJobShardingStrategy.class);
    }
}
